class UserToolSetting::SiteHealth < UserToolSetting
  
  validates_presence_of :site_url,
    :content_keyword,
    :report_hour,
    :name
    
  has_many :site_heart_beat_daily_stats,  
    :foreign_key => 'site_health_setting_id',
    :dependent => :destroy


  def todays_site_heart_beat_daily_stat
    SiteHeartBeatDailyStat.find_by_site_health_setting_id_and_created_on id, Date.today
  end

  def todays_stat
    todays_site_heart_beat_daily_stat
  end
  
  def stat_on on_when
    SiteHeartBeatDailyStat.find_by_site_health_setting_id_and_created_on id, on_when
  end
  
  def stat_between(started_on,ended_on)
    @stat_between ||= {}
    if @stat_between["#{started_on}-#{ended_on}"].nil?
      @stat_between["#{started_on}-#{ended_on}"] = SiteHeartBeatDailyStat.first(
        :select => "
          format(sum(response_time)/sum(available_site_heart_beats_count),0) as stat_avg_response_time,
          sum(available_site_heart_beats_count) as stat_available_site_heart_beats_count,
          sum(unavailable_site_heart_beats_count) as stat_unavailable_site_heart_beats_count,
          format(sum(available_site_heart_beats_count)*100/(sum(available_site_heart_beats_count) + sum(unavailable_site_heart_beats_count)),0) as stat_health_degree
        ",
        :conditions => [
          'site_health_setting_id = ? and ? <= created_on and created_on <= ? ',
          id,
          started_on,
          ended_on
        ]
      )
      @stat_between["#{started_on}-#{ended_on}"].attributes = {
        :the_fastest_heart_beat => SiteHeartBeatDailyStat.first(
          :conditions => [
              'site_heart_beat_daily_stats.site_health_setting_id = ?
               and ? <= site_heart_beat_daily_stats.created_on
               and site_heart_beat_daily_stats.created_on <= ? ',
              id,
              started_on,
              ended_on
            ],
            :include => :the_fastest_heart_beat,
            :order => 'site_heart_beats.response_time asc'
        ).the_fastest_heart_beat,
        :the_slowest_heart_beat => SiteHeartBeatDailyStat.first(
          :conditions => [
              'site_heart_beat_daily_stats.site_health_setting_id = ?
               and ? <= site_heart_beat_daily_stats.created_on
               and site_heart_beat_daily_stats.created_on <= ? ',
              id,
              started_on,
              ended_on
            ],
            :include => :the_slowest_heart_beat,
            :order => 'site_heart_beats.response_time desc'
        ).the_slowest_heart_beat
      }
#      @stat_between["#{started_on}-#{ended_on}"].attributes = {
#        :the_fastest_heart_beat => SiteHeartBeat::Available.first(
#            :conditions => [
#              'site_heart_beat_daily_stats.site_health_setting_id = ?
#               and ? <= site_heart_beats.created_at
#               and site_heart_beats.created_at <= ? #',
#              id,
#              started_on,
#              ended_on
#            ],
#            :include => [:site_heart_beat_daily_stat => :site_health_setting],
#            :order => 'site_heart_beats.response_time asc'
#          ),
#        :the_slowest_heart_beat => SiteHeartBeat::Available.last(
#            :conditions => [
#              'site_heart_beat_daily_stats.site_health_setting_id = ?
#              and ? <= site_heart_beats.created_at
#              and site_heart_beats.created_at <= ?#',
#              id,
#              started_on,
#              ended_on
#            ],
#            :include => [:site_heart_beat_daily_stat => :site_health_setting],
#            :order => 'site_heart_beats.response_time asc'
#          )
#      }
    end
    @stat_between["#{started_on}-#{ended_on}"]
  end    
  
  def this_week_stat
    stat_between Date.today.beginning_of_week,Date.today.end_of_week
  end
  
  def this_quarter_stat
    stat_between Date.today.beginning_of_quarter,Date.today.end_of_quarter
  end
  
  def this_month_stat
    stat_between Date.today.beginning_of_month,Date.today.end_of_month
  end
  
  def this_year_stat
    stat_between Date.today.beginning_of_year,Date.today.end_of_year
  end

  def send_email!(options = {})
    take_pulse if todays_stat.nil?
    send_email_block! do
      UserMailer.deliver_send_site_health self, options
    end
  end

  def send_sm!(pri = 1)
    send_sm_block! do
      Sm.create!( :user => user,
        :content =>  sm_content,
        :pri => pri)
    end
  end
  
  def syn_send_sm!(args = { :by => 'maple20' })
    send_sm_block! do
      if args[:by].to_s == 'lite'
        user.send_sm_by_lite_fetion sm_content
      else
        FetionSm.new( :mobile => user.mobile,
          :password => user.fetion_password,
          :content => sm_content ).create!
      end      
    end
  end
  
  def to_health_result_hash_key
    "site_url:#{site_url} content_keyword:#{content_keyword}"
  end
  
  def sm_content    
    take_pulse if todays_stat.nil?
    todays_stat.the_fastest_heart_beat ? "【#{todays_stat.site_health_setting.name}】今日的健康度是#{todays_stat.health_degree}%（#{todays_stat.available_site_heart_beats_count}次可用/#{todays_stat.unavailable_site_heart_beats_count}次故障），平均响应时间#{todays_stat.avg_response_time}ms，最快响应时间#{todays_stat.the_fastest_heart_beat.response_time}ms，最慢响应时间#{todays_stat.the_slowest_heart_beat.response_time}ms【麦吐司网】" : "【#{todays_stat.site_health_setting.name}】今日的健康度是#{todays_stat.health_degree}%（#{todays_stat.available_site_heart_beats_count}次可用/#{todays_stat.unavailable_site_heart_beats_count}次故障），平均响应时间#{todays_stat.avg_response_time}ms【麦吐司网】"
  end

  def take_pulse
    SiteHeartBeat.take_pulse! self
    touch
  end

  def self.take_pulses!    
    all(:conditions => ['updated_at < ?',1.hours.ago], :limit => 100, :order => 'updated_at asc').in_groups_of(10, false).each_with_object([]) do |settings,threads|
      threads << Thread.new(settings,[
          SiteHeartBeat,
          SiteHeartBeatDailyStat,
          SiteHeartBeat::Available,
          SiteHeartBeat::Unavailable
        ]) do |settings,classes|
        settings.each do | setting|
          setting.take_pulse
        end
      end
    end.each do |thread|
      thread.join
    end
  end
  
#  def self.take_pulses!
#    results = {}
#    settings = all(:conditions => ['updated_at < ?', 1.minutes.ago],:limit => 3000,:order => 'rand()')
#    settings.in_groups_of(10, false).each_with_object([]) do |settings,threads|
#      threads << Thread.new(settings,results,[SiteHeartBeat,SiteHeartBeatDailyStat]) do |settings,results,classes|
#        settings.each_with_index do | setting, index|
#          if results[setting.to_health_result_hash_key].present?
#            logger.debug "#{index}.  #{setting.name}'s health cached!"
#          else
#            logger.debug "#{index}. taking #{setting.name} pulse ...."
#            results[setting.to_health_result_hash_key] = SiteHeartBeat.take_pulse(setting)
#          end
#        end
#      end
#    end.each do |thread|
#      thread.join
#    end
#    settings.in_groups_of(10, false).each_with_object([]) do |settings,threads|
#      threads << Thread.new(settings,results) do |settings,results|
#        settings.each do | setting|
#          results[setting.to_health_result_hash_key] ||= SiteHeartBeat.take_pulse(setting)
#        end
#      end
#    end.each do |thread|
#      thread.join
#    end
#    settings.each do |setting|
#      results[setting.to_health_result_hash_key][:attributes][:site_heart_beat_daily_stat] = SiteHeartBeatDailyStat.find_or_create_by_site_health_setting_id_and_created_on(
#        setting.id,
#        Date.today
#      )
#      SiteHeartBeat.record_health_result!(results[setting.to_health_result_hash_key])
#      setting.touch
#    end
#  end

  def self.send_emails
    email_settings = all( :conditions => [
        '        report_hour = ?
          and (Date(emailed_at) < ?
            or (Date(emailed_at) = ? and Hour(emailed_at) < ? )
            or emailed_at is null)
          and allow_sms = ? ',
        Time.now.hour,
        Date.today,
        Date.today,
        Time.now.hour,
        'yes'
      ],
      :order => 'rand()'
    )
#    email_settings.in_groups_of(5,false).each_with_object([]) do |settings,threads|
#      threads << Thread.new(settings) do |settings|
#        settings.each do |setting|
#          puts "setting #{setting.tool.name} to #{setting.user.email}..."
#          setting.send_email 
#          puts 'end'
#        end
#      end
#    end.each do |thread|
#      thread.join
#    end
    email_settings.each do |setting|
      setting.send_email 
    end
    SmsEmailsDailyStat.today_stat.add_emails_count!(:emails_count => email_settings.size )
  end

  def self.send_sms(pri = 1)
    all( :conditions => [
        '        report_hour = ?
          and (Date(smed_at) < ?
            or (Date(smed_at) = ? and Hour(smed_at) < ? )
            or smed_at is null)
          and allow_sms = ? ',
        Time.now.hour,
        Date.today,
        Date.today,
        Time.now.hour,
        'yes'
      ]
    ).each do |setting|
      setting.send_sm(pri)
    end
    #in_groups_of(20, false).each_with_object([]) do |settings,threads|
    #  threads << Thread.new(settings) do |settings|
    #    settings.each do | setting|
    #      puts "setting #{setting.tool.name} to #{setting.user.mobile}..."
    #      setting.send_sm(pri)
    #      puts 'end'
    #    end
    #  end
    #end.each do |thread|
    #  thread.join
    #end
  end
end
